import { Application } from "mydog";
import { DEF } from "./definition/consts";
import { Dictionary, IUidSid } from "./definition/interface";
import { UserInfo } from "./definition/userInfo";

class LobbyManager {

  private static _instance: LobbyManager | undefined = undefined;
  public static getInstance(): LobbyManager {
    if (!this._instance) {
      this._instance = new LobbyManager();
    }
    return this._instance;
  }

  private constructor() { }

  private _app: Application = null as any;

  private _users: { [uid: number]: UserInfo } = {};
  private _matchMap: Dictionary<Array<UserInfo>> = {};

  public init(app: Application) {
    this._app = app;

    // for (var key in DEF.GAME.MODE) {
    //   console.log(key);
    // }
    this._matchMap[DEF.GAME.MODE.doudizhu] = new Array();
    this._matchMap[DEF.GAME.MODE.lushi] = new Array();

    // 匹配
    setInterval(this.update.bind(this), 1000);
  }

  // user
  public addUser(user: UserInfo) {
    if (!!user && !!user.id) {
      this._users[user.id] = user;
      this._users[user.id].online();
    }
  }

  public removeUser(uid: number) {
    const has = !!this._users[uid];
    if (has) {
      this._users[uid].offline();
      delete this._users[uid];
    }
  }

  public getUsers() {
    return this._users;
  }

  public getUserById(id: number) {
    return this._users[id];
  }

  public getUserByUsername(username: string) {
    for (let key in this._users) {
      if (this._users[key].username === username) {
        return this._users[key];
      }
    }
  }

  // match
  public startMatching(gameMode: number, uid: number) {
    const user = this.getUserById(uid);
    user.match();
    this._matchMap[gameMode].push(user);
  }

  public unmatch(gameMode: number, uid: number) {
    const user = this.getUserById(uid);
    user.unmatch();
    for (let key in this._matchMap) {
      const users = this._matchMap[key];
      for (let i = 0; i < users.length; i++) {
        if (users[i].id === uid) {
          users.splice(i, 1);
          return;
        }
      }
    }
  }

  private update() {
    for (let key in this._matchMap) {
      const gameMode = Number(key);
      const users = this._matchMap[gameMode];
      // console.log(`matching... gameMode:${gameMode} users:${users.length}`);
      switch (gameMode) {
        case DEF.GAME.MODE.doudizhu:
          while (users.length >= 3) {
            this.matchSuccess(gameMode, users.splice(0, 3));
          }
          break;
        case DEF.GAME.MODE.lushi:
          while (users.length >= 2) {
            this.matchSuccess(gameMode, users.splice(0, 2));
          }
          break;
        default: break;
      }
    }
  }

  private async matchSuccess(gameMode: number, users: Array<UserInfo>) {
    // const roomServers = this._app.getServersByType(DEF.SEVER.TYPE.ROOM);
    const simpleUsers = users.map(user => { return { uid: user.id, sid: user.sid } });
    const roomId = await this._app.rpcAwait(DEF.SEVER.ID.ROOM).room.main.onMatchRoom(gameMode, simpleUsers);
    users.forEach(user => { user.setRoom(roomId) });

    // 绑定 rid
    for (let i = 0; i < users.length; i++) {
      this._app.rpc(users[i].sid).connector.main.bindRoomId(users[i].id, roomId);
    }

    // 通知新房间创建
    // this.sendMessageToAll(cmd.)
  }

  // message
  public sendMessageToUid(route: number, uid: number, msg: any) {
    const users = this.getUsers();
    const uidsid = new Array<IUidSid>();
    for (let key in users) {
      if (users[key].id === uid) {
        uidsid.push({ uid: users[key].id, sid: users[key].sid });
        break;
      }
    }
    this._app.sendMsgByUidSid(route, msg, uidsid);
  }

  public sendMessageToAll(route: number, msg: any) {
    const users = this.getUsers();
    const uidsid = new Array<IUidSid>();
    for (let key in users) {
      uidsid.push({ uid: users[key].id, sid: users[key].sid });
    }
    this._app.sendMsgByUidSid(route, msg, uidsid);
  }

  public sendMessageToAllExceptUid(route: number, uid: number, msg: any) {
    const users = this.getUsers();
    const uidsid = new Array<IUidSid>();
    for (let key in users) {
      if (users[key].id !== uid) {
        uidsid.push({ uid: users[key].id, sid: users[key].sid });
      }
    }
    this._app.sendMsgByUidSid(route, msg, uidsid);
  }
}

export default LobbyManager.getInstance();
